package org.boot.fast.dao.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.boot.fast.core.mate.DatabaseMetaService;
import org.boot.fast.core.mate.entity.ColumnInfo;
import org.boot.fast.core.mate.entity.TableStructure;
import org.boot.fast.dao.entity.FastApiConfigDO;
import org.boot.fast.dao.mapper.FastApiConfigMapper;
import org.boot.fast.dao.service.FastApiConfigService;
import org.boot.fast.util.CollUtil;
import org.boot.fast.util.MappingUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class FastApiConfigServiceImpl extends ServiceImpl<FastApiConfigMapper, FastApiConfigDO> implements FastApiConfigService {

    @Resource
    private DatabaseMetaService metaService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<FastApiConfigDO> generateAllApi(String version, String table, String sysModule) {
        TableStructure tableStructure = metaService.getTableStructure(table);
        if (ObjectUtil.isEmpty(tableStructure)) {
            throw new RuntimeException("表[" + table + "]结构不存在");
        }
        //获取表名
        List<FastApiConfigDO> generateList = new ArrayList<>();
        int number = 1;
        //构建新增接口
        generateList.add(buildApiInsert(version, table, "insert"+(System.currentTimeMillis()+number++), sysModule, tableStructure));
        //构建批量新增接口
        generateList.add(buildApiInsertBatch(version, table, "inserts"+(System.currentTimeMillis()+number++), sysModule, tableStructure));
        //构建删除接口
        generateList.add(buildApiDelete(version, table, "delete"+(System.currentTimeMillis()+number++), sysModule, tableStructure));
        //构建批量删除接口
        generateList.add(buildApiDeleteBatch(version, table, "deletes"+(System.currentTimeMillis()+number++), sysModule, tableStructure));
        //构建更新接口
        generateList.add(buildApiUpdate(version, table, "update"+(System.currentTimeMillis()+number++), sysModule, tableStructure));
        //构建查询接口
        generateList.add(buildApiQuery(version, table, "query"+(System.currentTimeMillis()+number++), sysModule, tableStructure));
        //校验接口名
        this.saveBatch(generateList);
        return generateList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FastApiConfigDO generateInsertApi(String version, String table, String apiKey, String sysModule) {
        TableStructure tableStructure = metaService.getTableStructure(table);
        if (ObjectUtil.isEmpty(tableStructure)) {
            throw new RuntimeException("表[" + table + "]结构不存在");
        }
        String tableName = tableStructure.getTableInfo().getTableName();
        List<FastApiConfigDO> list = this.lambdaQuery()
                .eq(FastApiConfigDO::getApiKey, apiKey)
                .eq(FastApiConfigDO::getTableName, tableName)
                .eq(FastApiConfigDO::getVersion, version)
                .list();
        if (CollUtil.isNotEmpty(list)) {
            throw new RuntimeException("接口[" + apiKey + "]，版本[" + version + "]已存在");
        }
        FastApiConfigDO apiConfig = buildApiInsert(version, table, apiKey, sysModule, tableStructure);
        this.save(apiConfig);
        return apiConfig;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FastApiConfigDO generateInsertBatchApi(String version, String table, String apiKey, String sysModule) {
        TableStructure tableStructure = metaService.getTableStructure(table);
        if (ObjectUtil.isEmpty(tableStructure)) {
            throw new RuntimeException("表[" + table + "]结构不存在");
        }
        String tableName = tableStructure.getTableInfo().getTableName();
        List<FastApiConfigDO> list = this.lambdaQuery()
                .eq(FastApiConfigDO::getApiKey, apiKey)
                .eq(FastApiConfigDO::getTableName, tableName)
                .eq(FastApiConfigDO::getVersion, version)
                .list();
        if (CollUtil.isNotEmpty(list)) {
            throw new RuntimeException("接口[" + apiKey + "]，版本[" + version + "]已存在");
        }
        FastApiConfigDO apiConfig = buildApiInsertBatch(version, table, apiKey, sysModule, tableStructure);
        this.save(apiConfig);
        return apiConfig;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FastApiConfigDO generateDeleteApi(String version, String table, String apiKey, String sysModule) {
        TableStructure tableStructure = metaService.getTableStructure(table);
        if (ObjectUtil.isEmpty(tableStructure)) {
            throw new RuntimeException("表[" + table + "]结构不存在");
        }
        String tableName = tableStructure.getTableInfo().getTableName();
        List<FastApiConfigDO> list = this.lambdaQuery()
                .eq(FastApiConfigDO::getApiKey, apiKey)
                .eq(FastApiConfigDO::getTableName, tableName)
                .eq(FastApiConfigDO::getVersion, version)
                .list();
        if (CollUtil.isNotEmpty(list)) {
            throw new RuntimeException("接口[" + apiKey + "]，版本[" + version + "]已存在");
        }
        FastApiConfigDO apiConfig = buildApiDelete(version, table, apiKey, sysModule, tableStructure);
        this.save(apiConfig);
        return apiConfig;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FastApiConfigDO generateDeleteBatchApi(String version, String table, String apiKey, String sysModule) {
        TableStructure tableStructure = metaService.getTableStructure(table);
        if (ObjectUtil.isEmpty(tableStructure)) {
            throw new RuntimeException("表[" + table + "]结构不存在");
        }
        String tableName = tableStructure.getTableInfo().getTableName();
        List<FastApiConfigDO> list = this.lambdaQuery()
                .eq(FastApiConfigDO::getApiKey, apiKey)
                .eq(FastApiConfigDO::getTableName, tableName)
                .eq(FastApiConfigDO::getVersion, version)
                .list();
        if (CollUtil.isNotEmpty(list)) {
            throw new RuntimeException("接口[" + apiKey + "]，版本[" + version + "]已存在");
        }
        FastApiConfigDO apiConfig = buildApiDeleteBatch(version, table, apiKey, sysModule, tableStructure);
        this.save(apiConfig);
        return apiConfig;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FastApiConfigDO generateUpdateApi(String version, String table, String apiKey, String sysModule) {
        TableStructure tableStructure = metaService.getTableStructure(table);
        if (ObjectUtil.isEmpty(tableStructure)) {
            throw new RuntimeException("表[" + table + "]结构不存在");
        }
        String tableName = tableStructure.getTableInfo().getTableName();
        List<FastApiConfigDO> list = this.lambdaQuery()
                .eq(FastApiConfigDO::getApiKey, apiKey)
                .eq(FastApiConfigDO::getTableName, tableName)
                .eq(FastApiConfigDO::getVersion, version)
                .list();
        if (CollUtil.isNotEmpty(list)) {
            throw new RuntimeException("接口[" + apiKey + "]，版本[" + version + "]已存在");
        }
        FastApiConfigDO apiConfig = buildApiUpdate(version, table, apiKey, sysModule, tableStructure);
        this.save(apiConfig);
        return apiConfig;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FastApiConfigDO generateQueryApi(String version, String table, String apiKey, String sysModule) {
        TableStructure tableStructure = metaService.getTableStructure(table);
        if (ObjectUtil.isEmpty(tableStructure)) {
            throw new RuntimeException("表[" + table + "]结构不存在");
        }
        String tableName = tableStructure.getTableInfo().getTableName();
        List<FastApiConfigDO> list = this.lambdaQuery()
                .eq(FastApiConfigDO::getApiKey, apiKey)
                .eq(FastApiConfigDO::getTableName, tableName)
                .eq(FastApiConfigDO::getVersion, version)
                .list();
        if (CollUtil.isNotEmpty(list)) {
            throw new RuntimeException("接口[" + apiKey + "]，版本[" + version + "]已存在");
        }
        FastApiConfigDO apiConfig = buildApiQuery(version, table, apiKey, sysModule, tableStructure);
        this.save(apiConfig);
        return apiConfig;
    }


    private FastApiConfigDO buildApiInsert(String version, String table, String apiKey, String sysModule, TableStructure tableStructure) {
        FastApiConfigDO apiConfig = new FastApiConfigDO();
        apiConfig.setVersion(version);
        apiConfig.setTableName(table);
        apiConfig.setApiKey(apiKey);
        apiConfig.setSysModule(sysModule);
        apiConfig.setSqlType(1);
        apiConfig.setNote("新增");
        apiConfig.setExample("POST ---> /fast/api/"+version+"/"+apiKey+" ---> body请求体:{obj}");

        //获取主键
        List<String> primaryKeys = tableStructure.getPrimaryKeys();
        if (primaryKeys.isEmpty()) {
            throw new RuntimeException("表[" + table + "]没有主键");
        }
        String primaryKey = primaryKeys.get(0);
        //构建sql
        StringBuilder sql = new StringBuilder();
        sql.append("INSERT INTO ").append(table).append(" (");
        tableStructure.getColumns().forEach(column -> {
            if(!column.getColumnName().equals(primaryKey)){
                sql.append(column.getColumnName()).append(",");
            }
        });
        sql.deleteCharAt(sql.length() - 1);
        sql.append(") VALUES (");
        tableStructure.getColumns().forEach(column -> {
            if(!column.getColumnName().equals(primaryKey)){
                sql.append("#{").append(column.getColumnName()).append("},");
            }
        });
        sql.deleteCharAt(sql.length() - 1);
        sql.append(")");
        apiConfig.setSqlBody(sql.toString());
        return apiConfig;
    }

    private FastApiConfigDO buildApiInsertBatch(String version, String table, String apiKey, String sysModule, TableStructure tableStructure) {
        FastApiConfigDO apiConfig = new FastApiConfigDO();
        apiConfig.setVersion(version);
        apiConfig.setTableName(table);
        apiConfig.setApiKey(apiKey);
        apiConfig.setSysModule(sysModule);
        apiConfig.setSqlType(5);
        apiConfig.setNote("批量新增");
        apiConfig.setExample("POST ---> /fast/api/"+version+"/"+apiKey+" ---> body请求体:[{obj1},{obj2},...]");

        //获取主键
        List<String> primaryKeys = tableStructure.getPrimaryKeys();
        if (primaryKeys.isEmpty()) {
            throw new RuntimeException("表[" + table + "]没有主键");
        }
        String primaryKey = primaryKeys.get(0);
        //构建sql
        StringBuilder sql = new StringBuilder();
        sql.append("INSERT INTO ").append(table).append(" (");
        tableStructure.getColumns().forEach(column -> {
            if(!column.getColumnName().equals(primaryKey)){
                sql.append(column.getColumnName()).append(",");
            }
        });
        sql.deleteCharAt(sql.length() - 1);
        sql.append(") VALUES (");
        tableStructure.getColumns().forEach(column -> {
            if(!column.getColumnName().equals(primaryKey)){
                sql.append("#{").append(column.getColumnName()).append("},");
            }
        });
        sql.deleteCharAt(sql.length() - 1);
        sql.append(")");
        apiConfig.setSqlBody(sql.toString());
        return apiConfig;
    }

    private FastApiConfigDO buildApiDelete(String version, String table, String apiKey, String sysModule, TableStructure tableStructure) {
        FastApiConfigDO apiConfig = new FastApiConfigDO();
        apiConfig.setVersion(version);
        apiConfig.setTableName(table);
        apiConfig.setApiKey(apiKey);
        apiConfig.setSysModule(sysModule);
        apiConfig.setNote("删除");
        apiConfig.setSqlType(2);

        //获取主键
        List<String> primaryKeys = tableStructure.getPrimaryKeys();
        if (primaryKeys.isEmpty()) {
            throw new RuntimeException("表[" + table + "]没有主键");
        }
        String primaryKey = primaryKeys.get(0);
        apiConfig.setExample("DELETE ---> /fast/api/"+version+"/"+apiKey+"?"+primaryKey+"=主键值");

        //构建sql
        StringBuilder sql = new StringBuilder();
        sql.append("DELETE FROM ").append(table).append(" WHERE ").append(primaryKey).append(" = #{").append(primaryKey).append("}");
        apiConfig.setSqlBody(sql.toString());
        return apiConfig;
    }
    private FastApiConfigDO buildApiDeleteBatch(String version, String table, String apiKey, String sysModule, TableStructure tableStructure) {
        FastApiConfigDO apiConfig = new FastApiConfigDO();
        apiConfig.setVersion(version);
        apiConfig.setTableName(table);
        apiConfig.setApiKey(apiKey);
        apiConfig.setSysModule(sysModule);
        apiConfig.setNote("批量删除");
        apiConfig.setSqlType(2);

        //获取主键
        List<String> primaryKeys = tableStructure.getPrimaryKeys();
        if (primaryKeys.isEmpty()) {
            throw new RuntimeException("表[" + table + "]没有主键");
        }
        String primaryKey = primaryKeys.get(0);
        apiConfig.setExample("DELETE ---> /fast/api/"+version+"/"+apiKey+"?"+primaryKey+"_array=主键值1,主键值2,...");
        //构建sql
        StringBuilder sql = new StringBuilder();
        sql.append("DELETE FROM ").append(table).append(" WHERE ")
                .append(primaryKey)
                .append(" = #{")
                .append(primaryKey).append("_array")
                .append("}");
        apiConfig.setSqlBody(sql.toString());
        return apiConfig;
    }

    private FastApiConfigDO buildApiUpdate(String version, String table, String apiKey, String sysModule, TableStructure tableStructure) {
        FastApiConfigDO apiConfig = new FastApiConfigDO();
        apiConfig.setVersion(version);
        apiConfig.setTableName(table);
        apiConfig.setApiKey(apiKey);
        apiConfig.setSysModule(sysModule);
        apiConfig.setNote("更新");
        apiConfig.setSqlType(3);

        //获取主键
        List<String> primaryKeys = tableStructure.getPrimaryKeys();
        if (primaryKeys.isEmpty()) {
            throw new RuntimeException("表[" + table + "]没有主键");
        }
        String primaryKey = primaryKeys.get(0);
        apiConfig.setExample("PUT ---> /fast/api/"+version+"/"+apiKey+" ---> body请求体:{obj}");
        //构建sql
        StringBuilder sql = new StringBuilder();
        sql.append("UPDATE ").append(table).append(" SET ");
        tableStructure.getColumns().forEach(column -> {
            if(!column.getColumnName().equals(primaryKey)){
                sql.append(column.getColumnName()).append(" = #{").append(column.getColumnName()).append("},");
            }
        });
        sql.deleteCharAt(sql.length() - 1);
        sql.append(" WHERE ").append(primaryKey).append(" = #{").append(primaryKey).append("}");
        apiConfig.setSqlBody(sql.toString());
        return apiConfig;
    }

    private FastApiConfigDO buildApiQuery(String version, String table, String apiKey, String sysModule, TableStructure tableStructure) {
        FastApiConfigDO apiConfig = new FastApiConfigDO();
        apiConfig.setVersion(version);
        apiConfig.setTableName(table);
        apiConfig.setApiKey(apiKey);
        apiConfig.setSysModule(sysModule);
        apiConfig.setSqlType(4);
        apiConfig.setNote("查询");
        apiConfig.setExample("GET ---> /fast/api/"+version+"/"+apiKey+"?column1=value1&column2@like=value2,column3@in=1,2,3...");

        //获取所有的字段名
        List<String> columnNames = tableStructure.getColumns().stream().map(ColumnInfo::getColumnName).collect(Collectors.toList());

        //构建sql
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ");
        for (String columnName : columnNames) {
            sql.append(columnName).append(" AS ").append(MappingUtil.mappingToJava(columnName)).append(",");
        }
        sql.deleteCharAt(sql.length() - 1);
        sql.append(" FROM ").append(table);
        apiConfig.setSqlBody(sql.toString());
        return apiConfig;
    }
}
